﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using DataToShow.Network;

namespace DataToShow.FileSendAndReceive
{
    public class ServerClient
    {
        private const int BufferSize = 32768;
        private byte[] buffer=new byte[32768];
        private TcpClient client;
        public ServerClient(TcpClient client) 
        {
            this.client = client;
            
        }
        /// <summary>
        /// 发送文件 - 异步方法
        /// </summary>
        /// <param name="filePath"></param>
        public void BeginSendFile(string filePath)
        {
            ParameterizedThreadStart start =new ParameterizedThreadStart(BeginSendFile);
            string picName = Path.GetFileName(filePath);
            List<string> list = new List<string>();
            list.Add(filePath);
            list.Add(picName.Split('.')[0] + " ." + picName.Split('.')[1]);
            start.BeginInvoke(list, null, null);
        }

        /// <summary>
        /// 发送文件 - 异步方法
        /// </summary>
        /// <param name="filePath"></param>
        public void BeginSendFile(string filePath,string picName)
        {
            List<string> list = new List<string>();
            list.Add(filePath);
            list.Add(picName);
            ParameterizedThreadStart start = new ParameterizedThreadStart(BeginSendFile);
            start.BeginInvoke(list, null, null);
           
        }
        /// <summary>
        /// 发送文件 - 异步方法
        /// </summary>
        /// <param name="filePath"></param>
        private void BeginSendFile(object obj)
        {
            List<string> list = obj as List<string>;
            string filePath=list[0];
            string picName=list[1];
            SendFile(filePath,picName);
        }

        /// <summary>
        /// 发送文件 -- 同步方法
        /// </summary>
        /// <param name="filePath"></param>
        public void SendFile(string filePath,string picName)
        {
            TcpListener listener = new TcpListener(0);
            listener.Start();

            // 获取本地侦听的端口号
            IPEndPoint endPoint = listener.LocalEndpoint as IPEndPoint;
            int listeningPort = endPoint.Port;

            // 获取发送的协议字符串
           
            ProtocolHelper.FileProtocol protocol =
                new ProtocolHelper.FileProtocol(ProtocolHelper.FileRequestMode.Send, listeningPort, picName);
            string pro = protocol.ToString();
            AgreementHandler handler = new AgreementHandler(pro, CommandType.receive, client.GetStream());
            handler.Send(); 
            TcpClient localClient = listener.AcceptTcpClient();
            Console.WriteLine("Start sending file...");
            NetworkStream stream = localClient.GetStream();

            // 创建文件流
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            byte[] fileBuffer = new byte[32768];     // 每次传1KB
            int bytesRead;
            int totalBytes = 0;
            try
            {
                do
                {
                    lock (stream)
                    {
                    Thread.Sleep(20);           // 为了更好的视觉效果，暂停10毫秒:-)
                    bytesRead = fs.Read(fileBuffer, 0, fileBuffer.Length);
                    stream.Write(fileBuffer, 0, bytesRead);
                    totalBytes += bytesRead;            // 发送了的字节数
                    }
                } while (bytesRead > 0);
               
            }
            catch
            {
                Console.WriteLine("Server has lost...");
            }
            stream.Dispose();
            fs.Dispose();
            localClient.Close();
            listener.Stop();
        }
        /// <summary>
        /// 发送文件 - 异步方法
        /// </summary>
        /// <param name="filePath"></param>
        public void BeginReceiveFile(string name)
        {
            ParameterizedThreadStart start = new ParameterizedThreadStart(BeginSendFile);
            start.BeginInvoke(name, null, null);
        }
        /// <summary>
        /// 发送文件 - 异步方法
        /// </summary>
        /// <param name="filePath"></param>
        private void BeginReceiveFile(object obj)
        {
            string filePath = obj as string;
            receiveFile(filePath);
        }

        /// <summary>
        /// 接收文件
        /// </summary>
        /// <param name="protocol"></param>
        public void receiveFile(string fileName)
        {         
            TcpListener listener = new TcpListener(0);
            listener.Start();
            // 获取本地侦听的端口号
            IPEndPoint endPoint = listener.LocalEndpoint as IPEndPoint;
            int listeningPort = endPoint.Port;
            // 获取发送的协议字符串
            ProtocolHelper.FileProtocol protocol =
                new ProtocolHelper.FileProtocol(ProtocolHelper.FileRequestMode.Receive, listeningPort, fileName);
            string pro = protocol.ToString();
            AgreementHandler handler = new AgreementHandler(pro, CommandType.receive,client.GetStream());
            handler.Send(); 
            // 获取发送文件的流
            TcpClient localClient = listener.AcceptTcpClient();
            NetworkStream streamToClient = localClient.GetStream();
            if (!Directory.Exists(Environment.CurrentDirectory + @"\TempImage\"))
                Directory.CreateDirectory(Environment.CurrentDirectory + @"\TempImage\");
            //生成一个在当前目录下的文件名称
            string path = Environment.CurrentDirectory + "/TempImage/" + protocol.FileName;
            byte[] fileBuffer = new byte[32768]; // 每次收32KB
            try
            {
                using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
                {
                    // 从缓存buffer中读入到文件流中
                    int bytesRead;
                    int totalBytes = 0;
                    try
                    {
                        do
                        {
                            bytesRead = streamToClient.Read(buffer, 0, BufferSize);
                            fs.Write(buffer, 0, bytesRead);
                            totalBytes += bytesRead;
                        } while (bytesRead > 0);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                    //Console.WriteLine("Total {0} bytes received, Done!", totalBytes);
                    streamToClient.Dispose();
                    localClient.Close();
                }
            }
            catch 
            {
                streamToClient.Dispose();
                localClient.Close();
            }
          
        }

        /// <summary>
        /// 接收文件
        /// </summary>
        /// <param name="protocol"></param>
        private void receiveFile(int port, string ip, string picName)
        {
            // 使用新端口号，获得远程用于接收文件的端口
            IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(ip), port);

            // 连接到远程客户端
            TcpClient localClient;
            try
            {
                localClient = new TcpClient();
                localClient.Connect(endpoint);
            }
            catch
            {
                return;
            }

            // 获取发送文件的流
            NetworkStream streamToClient = localClient.GetStream();
            if (!Directory.Exists(Environment.CurrentDirectory + @"\EventImage\"))
                Directory.CreateDirectory(Environment.CurrentDirectory + @"\EventImage\");
            string path = Environment.CurrentDirectory + @"\EventImage\" + picName;
            byte[] fileBuffer = new byte[32768];
            int bytesRead;
            if (picName == "")
            {
                bytesRead = streamToClient.Read(new byte[1], 0, 1);
            }
            else
            {

                int totalBytes = 0;
                FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write);
                try
                {
                    do
                    {
                        bytesRead = streamToClient.Read(buffer, 0, BufferSize);
                        fs.Write(buffer, 0, bytesRead);
                        totalBytes += bytesRead;

                    }
                    while (bytesRead > 0);
                    fs.Dispose();
                    if (totalBytes == 1)
                    {
                        File.Delete(path);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }

            }

            streamToClient.Dispose();

            localClient.Close();
        }

    }
}
